/**
 * @author Rid King
 * @since 2017-06-11
 * @version 0.0.0
 * @description 消费者
 */
'user strict';

class Observer {
    /**
     * @description 消费构造
     * @param destination <Function/Observer> 消费者对象
     * @param error <Function> 失败回调
     * @param complete <Function> 结束回调
    */
    constructor (destination, error, complete) {
        // 函数形式
        if (typeof destination === 'function') {
            // 代理对象
            destination = {
                next: destination,
                error: error,
                complete: complete
            }
        }
        
        this.destination = destination
    }

    /**
     * @description 执行下一步
     * @param value <any> 传入值
     * [@param arg <any> 更多传入值]
    */
    next (value) {
        // 尚未取消订阅，且包含next方法
        if (!this.isUnsubscribed && typeof this.destination.next === 'function') {
            try {
                this.destination.next.apply(this, arguments)
            } catch (err) {
                // 出现异常时，取消订阅释放资源，再抛出异常
                this.unsubscribe()
                throw err
            }
        }
    }

    /**
     * @description 错误执行
     * @param err <any> 传入值
     * [@param arg <any> 更多传入值]
    */
    error (err) {
        // 尚未取消订阅，且包含error方法
        if (!this.isUnsubscribed && typeof this.destination.error === 'function') {
            try {
                this.destination.error.apply(this, arguments)
            } catch (e) {
                // 出现异常时，取消订阅释放资源，再抛出异常
                this.unsubscribe()
                throw e
            }
        }
    }

    /**
     * @description 完成
    */
    complete () {
        // 尚未取消订阅，且包含complete方法
        if (!this.isUnsubscribed && typeof this.destination.complete === 'function') {
            try {
                this.destination.complete.apply(this, arguments)
            } catch (e) {
                // 出现异常时，取消订阅释放资源，再抛出异常
                this.unsubscribe()
                throw e
            }
        }

        // 未取消订阅时取消
        if (!this.isUnsubscribed) {
            this.unsubscribe()
        }
    }

    /**
     * @description 取消订阅
    */
    unsubscribe () {
        if (!this.isUnsubscribed && typeof this.unsub === 'function') {
            this.unsub()
        }
        this.isUnsubscribed = true
    }
}

export default Observer